class_name GameplayAbilitySpec
extends RefCounted

## 能力是否激活
var active: bool

## 能力
var ability: GameplayAbility

## 能力释放的对象
var targets: Array

## 能力是否过期
var expired: bool


func _init(init_ability: GameplayAbility) -> void:
	active = true
	ability = init_ability
	targets = capture_targets()
	expired = false


func capture_targets() -> Array:
	return _capture_targets()


func apply() -> void:
	# INFO:
	# 有可能在应用能力的瞬间无法决定应用的对象，理论上可以提供一个对象捕获的组件，直接指定对象或者持续检测对象等。
	# 假如有一个造成范围伤害的炮弹，当炮弹触地或者遇敌（在炮弹对象中检测）需要爆炸时（需要释放伤害能力时），需要捕获范围内的对象应用能力，
	# 相当于在一个 GameplayAbilitySpec 中有多个目标对象，而不是对每个目标对象都创建一个 GameplayAbilitySpec（暂时如此）。
	# 能力在应用时不存在延迟应用的说法，即在应用时就需要获得应用对象，然后应用。
	# 但是有些能力看似不需要对象，比如开枪，因为开枪时是在释放子弹，由子弹造成伤害，此时可以考虑两种处理方法：
	# 1. 不把开枪当作能力，使用状态机进入开枪状态。
	# 2. 把开枪当作能力，但是应用对象是自己。
	# 总之，暂时保持能力在应用时都有应用对象。（我暂时也不清楚应用对象留空是否合理）
	for target in targets:
		target.effect_manager.attach_effects(ability.ability_asset.granted_effects, ability.owner)
	
	for target in targets:
		_apply(target)


func on_update(delta: float) -> void:
	if not expired and active:
		_on_update(delta)


func activate() -> void:
	# INFO:
	# 可以注意到，GameplayEffect 的激活、失活都在 GameplayEffectManager 中实现，
	# 这是因为 GameplayEffect 改变时需要修改的属性都在 GameplayEffectManager 中缓存。
	# 而 GameplayAbility 的激活和失活则可以单独由自己处理，没有必要全都移动到 GameplayAbilityManager 中。
	# 另一个原因是需要在 GameplayAbilitySpec 中调用 end_ability，
	# 而将 end_ability 的实现全都写在 GameplayAbilityManager 后，GameplayAbilitySpec 中调用 end_ability 就很困难，
	# 因此打算 GameplayAbilitySpec 实现自己可以实现的全部逻辑，GameplayAbilityManager 负责调用。
	if expired and not active:
		return
	
	active = true

	for target in targets:
		target.effect_manager.activate_effects(ability.ability_asset.granted_effects)


func deactivate() -> void:
	if expired and active:
		return
	
	active = false

	for target in targets:
		target.effect_manager.deactivate_effects(ability.ability_asset.granted_effects)


func end_ability() -> void:
	if expired:
		return
	
	expired = true
	
	for target in targets:
		target.effect_manager.detach_effects(ability.ability_asset.granted_effects, ability.owner)

	_end_ability()


#region Need to override
func _capture_targets() -> Array:
	Logger.fatal("Need to override")
	return []


func _apply(_target: Variant) -> void:
	Logger.fatal("Need to override")


func _on_update(_delta: float) -> void:
	Logger.fatal("Need to override")


func _end_ability() -> void:
	Logger.fatal("Need to override")
#endregion
